package com.boarsoft.boar.gateway.weixin.common;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.CertificateException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.boarsoft.boar.gateway.wechat.common.WechatConfig;
import com.boarsoft.boar.gateway.weixin.common.http.WXHttpProcesser;
import com.boarsoft.boar.gateway.weixin.entity.WxPlatformUser;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import net.sf.json.JSONObject;

public class WeixinPlatformUser {

	private static Logger log = LoggerFactory.getLogger(WeixinPlatformUser.class);

	private String type = "url";
	private static Map<String, Object> platformUserMap = new HashMap<String, Object>();
	private AccessToken accessToken;
	private WxPlatformUser platformUser;

	public static String URL_PRE = WechatConfig.getProperty("weixin.apiUrl");

	private X509TrustManager xtm = new X509TrustManager() {
		@Override
		public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		@Override
		public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType)
				throws CertificateException {
			// TODO Auto-generated method stub

		}

		@Override
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			// TODO Auto-generated method stub
			return null;
		}
	};

	// Create an class to trust all hosts
	private HostnameVerifier hnv = new HostnameVerifier() {
		public boolean verify(String hostname, SSLSession session) {
			return true;
		}
	};

	public WeixinPlatformUser(String account, String password, String appId, String secret) {
		if (platformUser == null) {
			platformUser = new WxPlatformUser();
		}
		platformUser.setAccount(account);
		platformUser.setPassword(password);
		this.accessToken = new AccessToken(this, appId, secret);
	}

	public WeixinPlatformUser(WxPlatformUser platformUser) {
		this.platformUser = platformUser;
		this.accessToken = new AccessToken(this, platformUser.getAppid(), platformUser.getSecret());
	}

	public WxPlatformUser getPlatformUser() {
		return platformUser;
	}

	public String getType() {
		return this.type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public void login(String imgCode) throws Exception {
		String loginUrl = "https://m5?lang=zh_CN&username=" + platformUser.getAccount() + "&pwd=" + platformUser.getPassword()
				+ "&f=json&imgcode=" + imgCode;
		String resultJson = this.getPostResult(loginUrl);
		int pos = resultJson.indexOf("token=");
		if (pos > 0) {
			String s1 = resultJson.substring(pos + 6);
			String token = s1.substring(0, s1.indexOf("\","));
			platformUser.setToken(token);
			// this.cookie = null;
			// this.fakeId = (String)this.cookie.get("slave_user");
			platformUserMap.put(token, this);
		} else {
			log.info("登录失败:" + resultJson);
		}
	}

	/**
	 * 获取平台账号信息
	 */
	public Map getPlatformUserInfo() throws Exception {
		String url = "https://mp.weixin.qq.com/cgi-bin/userinfopage?t=wxm-setting&token=" + platformUser.getToken()
				+ "&lang=zh_CN";
		String resultJson = this.getPostResult(url);
		Document doc = Jsoup.parse(resultJson);
		Elements scriptElement = doc.select("script#json-setting");
		String scriptContent = scriptElement.html();
		JSONObject jsonObject = JSONObject.fromObject(scriptContent);
		return jsonObject;
	}

	/**
	 * 获取关注用户信息
	 * 
	 * @param openId
	 * @return
	 * @throws Exception
	 */
	public Map getSubscribeUserInfo(String openId) throws Exception {
		String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" + accessToken.getAccessToken() + "&openid="
				+ openId + "&lang=zh_CN";

		String resultJson = this.getResult(url);
		JSONObject jsonObject = JSONObject.fromObject(resultJson);
		return jsonObject;
	}

	public WeixinPlatformUser getPlatformUserByToken(String token) {
		return (WeixinPlatformUser) platformUserMap.get(token);
	}

	public boolean isLoginRequest(String url) {
		return url.indexOf("login?") > 0;
	}

	/**
	 * post请求
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public String getPostResult(String url) throws Exception {
		return getResultByMethod(url, true);
	}

	/**
	 * get请求
	 * 
	 * @param url
	 * @return
	 * @throws Exception
	 */
	public String getResult(String url) throws Exception {
		return getResultByMethod(url, false);
	}

	public String getResultByMethod(String url, boolean isPost) throws Exception {
		return getResultByMethod(url, isPost, "");
	}

	public String getResultByMethod(String url, boolean isPost, String postData) throws Exception {
		String reqMethod = "GET";
		if (isPost) {
			reqMethod = "POST";
		}
		return WXHttpProcesser.sendRequest(url, reqMethod, postData);
	}

	/**
	 * 
	 * 
	 * */
	public Map<String, Object> getPostResult(String url, boolean ifOld) {
		return getResultByMethod(url, true, false);
	}

	public Map<String, Object> getResult(String url, boolean ifOld) {
		return getResultByMethod(url, false, false);
	}

	public Map<String, Object> getResultByMethod(String url, boolean isPost, boolean ifOld) {
		return getResultByMethod(url, isPost, "", false);
	}

	public Map<String, Object> getResultByMethod(String url, boolean isPost, String postData, boolean ifOld) {

		if (WXHttpProcesser.isProxy) {
			System.setProperty("http.proxyHost", WXHttpProcesser.proxyHost);
			System.setProperty("http.proxyPort", String.valueOf(WXHttpProcesser.proxyPort));
			System.setProperty("https.proxyHost", WXHttpProcesser.proxyHost);
			System.setProperty("https.proxyPort", String.valueOf(WXHttpProcesser.proxyPort));
		}
		if (!url.startsWith("http")) {
			url = URL_PRE + url;
		}
		log.debug("发送消息(send msg):" + postData);

		Map<String, Object> returnMap = new HashMap<String, Object>();
		Map returnCookieMap = new HashMap();
		byte[] in2b = new byte[0];
		try {
			URL reqUrl = new URL(url);
			HttpURLConnection reqConnection = null;
			// 判断是http请求还是https请求
			if (reqUrl.getProtocol().toLowerCase().equals("https")) {
				SSLContext sslContext = null;
				try {
					// 实例化SSL上下文
					sslContext = SSLContext.getInstance("TLS");// 直接用SSL或者TLS也可以
					TrustManager[] xtmArray = new TrustManager[] { xtm };
					// 初始化SSL上下文
					sslContext.init(null, xtmArray, new java.security.SecureRandom());
				} catch (Exception e) {
					throw e;
				}
				// 设置默认的SSLSocketFactory
				if (sslContext != null) {
					HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
				}
				HttpsURLConnection.setDefaultHostnameVerifier(hnv);
				// 建立URLConnection连接
				reqConnection = (HttpsURLConnection) reqUrl.openConnection();
			} else {
				reqConnection = (HttpURLConnection) reqUrl.openConnection();
			}
			if (isPost) {
				reqConnection.setRequestMethod("POST");
			} else {
				reqConnection.setRequestMethod("GET");
			}

			reqConnection.setRequestProperty("User-Agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.1; Trident/6.0");
			reqConnection.setRequestProperty("Host", "mp.weixin.qq.com");
			reqConnection.setRequestProperty("DNT", "1");
			reqConnection.setRequestProperty("Connection", "keep-alive");
			reqConnection.setRequestProperty("Referer", "https://mp.weixin.qq.com/");
			reqConnection.setDoInput(true);
			reqConnection.setDoOutput(isPost);
			if (isPost) {
				OutputStream output = null;
				try {
					output = reqConnection.getOutputStream();
					output.write(postData.getBytes("UTF-8"));
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					output.close();
				}
			}
			reqConnection.connect();
			Map<String, List<String>> map = reqConnection.getHeaderFields();
			List returnCookies = (List) map.get("Set-Cookie");

			if (returnCookies != null) {
				for (int i = 0; i < returnCookies.size(); i++) {
					String cookieStr = (String) returnCookies.get(i);
					cookieStr = cookieStr.substring(0, cookieStr.indexOf(";"));
					int index = cookieStr.indexOf("=");
					if (index > 0) {
						returnCookieMap.put(cookieStr.substring(0, index), cookieStr.substring(index + 1));
					}
				}
			}
			if (!isLoginRequest(url)) {
				if ("EXPIRED".equals(returnCookieMap.get("slave_sid"))) {
					this.login("");
				}
			}
			InputStream input = reqConnection.getInputStream();
			ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
			byte[] buff = new byte[100];
			int rc = 0;
			int a = input.available();
			while ((rc = input.read(buff, 0, 100)) > 0) {
				swapStream.write(buff, 0, rc);
			}
			in2b = swapStream.toByteArray();
		} catch (Exception e) {
			log.error("发送消息(send msg)失败：", e);
			returnMap.put("respCode", "EBWX0000");
			return returnMap;
		}
		log.info("发送消息结果(send result):" + new String(in2b));
		returnMap.put("cookie", returnCookieMap);
		returnMap.put("result", in2b);
		return returnMap;
	}

	/**
	 * 发送模板消息
	 */
	public Map<String, Object> sendTemplateMsg(String sendMsg) {
		log.info("发送模板消息开始:{}", sendMsg);
		Map<String, Object> reMap = new HashMap<String, Object>();
		try {
			String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken.getAccessToken();
			Map<String, Object> respMap = getResultByMethod(url, true, sendMsg, false);
			byte[] result = (byte[]) respMap.get("result");

			String resultJson = new String(result, "UTF-8");
			Map<String, String> resultMap = new HashMap<String, String>();
			resultMap = new Gson().fromJson(resultJson, new TypeToken<Map<String, String>>() {
			}.getType());
			String errcode = resultMap.get("errcode");
			String errmsg = (String) resultMap.get("errmsg");
			if ("0".equals(errcode)) {
				reMap.put("respCode", "000000000");
				reMap.put("respMsg", "成功");
				reMap.put("msgid", resultMap.get("msgid"));
			} else if ("-1".equals(errcode)) {
				reMap.put("respCode", "EBWX000002");
				reMap.put("respMsg", "微信系统繁忙");
			} else {
				reMap.put("respCode", "EBWX0" + errcode);
				reMap.put("respMsg", errmsg);
			}
		} catch (Exception e) {
			log.error("发送模板消息错误：", e);
			reMap.put("respCode", "EBWX000001");
			reMap.put("respMsg", "发送模板消息错误");
		}
		;
		log.info("发送模板消息结束:{}", reMap);
		return reMap;
	}

	public static void main(String args[]) throws Exception {
		WeixinPlatformUser w = new WeixinPlatformUser("scrcu_96633@163.com", "ceishi123=", "wx4e5565edc1b8fabd",
				"229f9386ee2d97af044dad2ce52d2018");
		String ss = "{\"touser\":\"o7BXVv8Tmg_j9exUzpEVgpLmVeIs\","
				+ "\"template_id\":\"3Qs5W_dkM02KM3fcO98Zlm9H3Hp7ucXke6rYTRLr1J4\"," + "\"data\":{" + "\"acctNo\": {"
				+ "\"value\":\"**0807\"," + "\"color\":\"#00ff00\"" + "}," + "\"time\":{" + "\"value\":\"2014年9月22日\","
				+ "\"color\":\"#173177\"" + "}," + "\"amt\": {" + "\"value\":\"39.8\"," + "\"color\":\"#173177\"" + "},"
				+ "\"remake\":{" + "\"value\":\"欢迎再次购买！\"," + "\"color\":\"#173177\"" + "}" + "}" + "}";
		w.sendTemplateMsg(ss);
	}
}
